package com.ybkj.daijia.server.controller;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.ybkj.daijia.CSRFTokenManager;
import com.ybkj.daijia.ServiceSetting;
import com.ybkj.daijia.Setting;
import com.ybkj.daijia.api.common.LineUtil;
import com.ybkj.daijia.common.Distance;
import com.ybkj.daijia.common.MemberOrderVo;
import com.ybkj.daijia.common.OrderLocationGroup;
import com.ybkj.daijia.common.PageVo;
import com.ybkj.daijia.common.Pager;
import com.ybkj.daijia.common.PointVo;
import com.ybkj.daijia.common.Principal;
import com.ybkj.daijia.common.Result;
import com.ybkj.daijia.page.Page;
import com.ybkj.daijia.server.errand.SelectPrice;
import com.ybkj.daijia.server.event.model.ActivityCheckEvent;
import com.ybkj.daijia.server.event.model.OperationLogEvent;
import com.ybkj.daijia.server.event.model.zhuanxian.ZhuanxianOrderCallBackEvent;
import com.ybkj.daijia.server.event.model.zhuanxian.ZhuanxianOrderCreateEvent;
import com.ybkj.daijia.server.event.model.zhuanxian.ZhuanxianOrderPaidanEvent;
import com.ybkj.daijia.server.event.model.zhuanxian.ZhuanxianOrderRecordEvent;
import com.ybkj.daijia.server.exception.NoPermissionException;
import com.ybkj.daijia.server.mc.Passenger;
import com.ybkj.daijia.server.model.Area;
import com.ybkj.daijia.server.model.ChargeStartDistance;
import com.ybkj.daijia.server.model.ChargeStartTime;
import com.ybkj.daijia.server.model.Company;
import com.ybkj.daijia.server.model.Driver;
import com.ybkj.daijia.server.model.OrderLocation;
import com.ybkj.daijia.server.model.OrderLocationMany;
import com.ybkj.daijia.server.model.PlaceInputHistory;
import com.ybkj.daijia.server.model.Role;
import com.ybkj.daijia.server.model.WeixinManagerXOrder;
import com.ybkj.daijia.server.reactor.ReactorVo;
import com.ybkj.daijia.server.sales.Activity.ActivityEvent;
import com.ybkj.daijia.server.sales.Coupon;
import com.ybkj.daijia.server.service.AreaService;
import com.ybkj.daijia.server.service.CompanyService;
import com.ybkj.daijia.server.service.CouponService;
import com.ybkj.daijia.server.service.DriverService;
import com.ybkj.daijia.server.service.ErrandService;
import com.ybkj.daijia.server.service.FreightService;
import com.ybkj.daijia.server.service.MemberService;
import com.ybkj.daijia.server.service.OrderLocationManyService;
import com.ybkj.daijia.server.service.OrderLocationService;
import com.ybkj.daijia.server.service.OrderService;
import com.ybkj.daijia.server.service.PlaceInputHistoryService;
import com.ybkj.daijia.server.service.RoleService;
import com.ybkj.daijia.server.service.WeixinManagerService;
import com.ybkj.daijia.server.service.WeixinManagerXOrderService;
import com.ybkj.daijia.server.service.ZhuancheService;
import com.ybkj.daijia.server.service.ZhuanxianService;
import com.ybkj.daijia.server.zhuanxian.Car;
import com.ybkj.daijia.server.zhuanxian.Line;
import com.ybkj.daijia.server.zhuanxian.Order;
import com.ybkj.daijia.server.zhuanxian.OrderLngLat;
import com.ybkj.daijia.server.zhuanxian.OrderOrbit;
import com.ybkj.daijia.server.zhuanxian.OrderReview;
import com.ybkj.daijia.server.zhuanxian.OrderStatus;
import com.ybkj.daijia.serverUtils.ExcelUtil;
import com.ybkj.daijia.serverUtils.HttpClientUtil;
import com.ybkj.daijia.serverUtils.ServiceUtil;
import com.ybkj.daijia.serverUtils.SettingUtils;
import com.ybkj.daijia.serverUtils.UseAllDataUtil;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("zhuanxian")
public class ZhuanxianController {
    @Autowired
    private ZhuanxianService zhuanxianService;
    @Autowired
    private DriverService driverService;
    @Autowired
    private CompanyService companyService;
    @Autowired
    private AreaService areaService;
    @Autowired
    private WeixinManagerService weixinManagerService;
    @Autowired
    private WeixinManagerXOrderService weixinManagerXOrderService;
    @Autowired
    private ApplicationEventMulticaster applicationEventMulticaster;
    @Autowired
    private OrderService orderService;
    @Autowired
    private ErrandService errandService;
    @Autowired
    private FreightService freightService;
    @Autowired
    private ZhuancheService zhuancheService;
    @Autowired
    private SettingUtils settingUtils;
    @Autowired
    private CouponService couponService;
    @Autowired
    private OrderLocationManyService orderLocationManyService;
    @Autowired
    private OrderLocationService orderLocationService;
    @Autowired
    private MemberService memberService;
    @Autowired
    private PlaceInputHistoryService placeInputHistoryService;
    @Autowired
    private RoleService roleService;

    /**
     * 线路去重
     *
     * @return
     */
    public List<Line> distinctLine(List<Line> lines) {
        //用于存放需要隐藏的线路id
        List<Long> lineIdList = new ArrayList<>();
        //用于存放需要隐藏的线路
        List<Line> lineList = new ArrayList<>();
        for (Line line : lines) {
            String[] splitName = line.getName().split("-");
            String returnLineName = splitName[1] + "-" + splitName[0];
            boolean exist = false;
            for (Long id : lineIdList) {
                if (id.equals(line.getId())) {
                    exist = true;
                }
            }
            if (exist) {
                continue;
            }
            for (Line l : lines) {
                if (l.getName().equals(returnLineName)) {
                    lineList.add(l);
                    lineIdList.add(l.getId());
                }
            }
        }
        for (Line line : lineList) {
            lines.remove(line);
        }
        return lines;
    }

    public List<Line> distinctLine_BackUp(List<Line> lines) {
        //用于存放需要隐藏的线路id
        List<Long> lineIdList = new ArrayList<>();
        //用于存放需要隐藏的线路
        List<Line> lineList = new ArrayList<>();
        for (Line line : lines) {
            String startAddress = line.getStartAddress();
            String endAddress = line.getEndAddress();
            boolean exist = false;
            for (Long id : lineIdList) {
                if (id.equals(line.getId())) {
                    exist = true;
                }
            }
            if (exist) {
                continue;
            }
            for (Line l : lines) {
                if (l.getStartAddress().equals(endAddress) && l.getEndAddress().equals(startAddress)) {
                    lineList.add(l);
                    lineIdList.add(l.getId());
                }
            }
        }
        for (Line line : lineList) {
            lines.remove(line);
        }
        return lines;
    }

    /**
     * 查询线路
     *
     * @return
     */
    @RequestMapping("findLines")
    public @ResponseBody
    Map<String, Object> findLines() {
        Principal principal = (Principal) SecurityUtils.getSubject().getPrincipal();
        List<Line> lines = null;
        if (principal.isCompanyType()) {
            lines = zhuanxianService.queryLines(null);
        } else {
            lines = zhuanxianService.queryLines(principal.getCompanyId());
        }
        if (null == lines) {
            return null;
        }
        lines = distinctLine(lines);
        List<Map<String, Object>> list = new ArrayList<>();
        Map<String, String> lineModel = new HashMap<>();
        Map<String, Object> allLine = new HashMap<>();
//        allLine.put("label","所有线路");
//        allLine.put("value",0l);
        list.add(allLine);
        for (int i = 0; i < lines.size(); i++) {
            Line line = lines.get(i);
            lineModel.put("line" + i, "");
        }
        Map<String, Object> res = new HashMap<>();
        res.put("lineList", lines);
        res.put("lineModel", lineModel);
        return res;
    }

    @RequestMapping(value = "add", method = RequestMethod.GET)
    public ModelAndView add(HttpSession session) {

        Subject subject = SecurityUtils.getSubject();

        if (subject.isPermitted("zhuanxian")) {
            ModelAndView mv = new ModelAndView();

            Subject currentUser = SecurityUtils.getSubject();
            Principal principal = (Principal) currentUser.getPrincipal();

            Company company = companyService.findOne(principal.getCompanyId());

            mv.addObject("companyId", company.getId());
            mv.addObject("companys", companyService.findAll());
            mv.addObject("weixinManagers", weixinManagerService.findByCompany(company.getId()));
            mv.addObject("address", company.getCityName());
            mv.addObject("default", "zhuanxian");
            mv.addObject("mainCompany", String.valueOf(principal.isCompanyType()));
            List<Line> lines = null;
            if (principal.isCompanyType()) {
                lines = zhuanxianService.queryLines(null);
            } else {
                lines = zhuanxianService.queryLines(principal.getCompanyId());
            }
            /**去掉重复的逆向线路*/
            lines = distinctLine(lines);
            mv.addObject("lines", lines);
            mv.addObject(CSRFTokenManager.CSRF_PARAM_NAME, CSRFTokenManager.getTokenForSession(session));
            mv.setViewName("order/add");

            return mv;
        } else {
            throw new NoPermissionException();
        }

    }

    // 追加
    @RequestMapping(value = "addmore/{id}", method = RequestMethod.GET)
    public ModelAndView addmore(HttpSession session, @PathVariable("id") Long id) {

        Subject subject = SecurityUtils.getSubject();
        Principal principal = (Principal) subject.getPrincipal();
        if (subject.isPermitted("zhuanxian")) {
            ModelAndView mv = new ModelAndView();

            Order order = zhuanxianService.findOne(id);
            Company company = companyService.findOne(order.getCompanyId());
            mv.addObject("companyId", order.getCompanyId());
            mv.addObject("companys", companyService.findAll());
            List<Line> lines = null;
            if (principal.isCompanyType() && principal.getCompanyId()
                .equals(order.getCompanyId())) {
                lines = zhuanxianService.queryLines(null);
            } else {
                lines = zhuanxianService.queryLines(order.getCompanyId());
            }
            mv.addObject("weixinManagers", weixinManagerService.findByCompany(company.getId()));
            mv.addObject("lines", lines);
            mv.addObject("lng", order.getStartLng());
            mv.addObject("lat", order.getStartLat());
            if (order.getServerTime().before(new Date())) {
                order.setServerTime(new Date());
            }
            mv.addObject("zhuanxianOrder", order);
            mv.addObject("zhuanOrder", new com.ybkj.daijia.server.zhuan.Order());
            mv.addObject("errand", new com.ybkj.daijia.server.errand.Order());

            WeixinManagerXOrder weixinManagerXOrder = weixinManagerXOrderService.findByOrderId(id);
            if (null != weixinManagerXOrder) {
                mv.addObject("weixinManagerId", weixinManagerXOrder.getManagerId());
            }

            mv.addObject(CSRFTokenManager.CSRF_PARAM_NAME, CSRFTokenManager.getTokenForSession(session));
            mv.addObject("default", "zhuanxian");
            mv.addObject("mainCompany", String.valueOf(principal.isCompanyType()));
            mv.setViewName("order/addmore");

            return mv;
        } else {
            throw new NoPermissionException();
        }
    }

    @RequestMapping(value = "jump", method = RequestMethod.GET)
    public ModelAndView jump() throws ParseException {
        Subject subject = SecurityUtils.getSubject();
        Principal principal = (Principal) subject.getPrincipal();

        ModelAndView mv = new ModelAndView();
        if (subject.isPermitted("zhuanxianCar")) {
            List<Line> lines = null;
            if (principal.isCompanyType()) {
                lines = zhuanxianService.queryLines(null);
            } else {
                lines = zhuanxianService.queryLines(principal.getCompanyId());
            }
            List<Company> companys = companyService.findAll();

            mv.addObject("companys", companys);
            mv.addObject("lines", lines);
            mv.setViewName("zhuanxian/cars");
            return mv;
        } else if (subject.isPermitted("zhuanxianLine")) {
            if (principal.isCompanyType()) {
                mv.addObject("companys", companyService.findAll());
            }
            mv.addObject("companyId", principal.getCompanyId());
            mv.addObject("arealist", areaService.listAll());
            mv.setViewName("zhuanxian/lines");
            return mv;
        } else {
            throw new NoPermissionException();
        }

    }

    @RequestMapping(value = "cars", method = RequestMethod.GET)
    public ModelAndView cars() throws ParseException {
        Subject subject = SecurityUtils.getSubject();
        ModelAndView mv = new ModelAndView();
        if (subject.isPermitted("zhuanxianCar")) {
            Principal principal = (Principal) subject.getPrincipal();
            List<Line> lines = null;
            if (principal.isCompanyType()) {
                lines = zhuanxianService.queryLines(null);
            } else {
                lines = zhuanxianService.queryLines(principal.getCompanyId());
            }
            List<Company> companys = companyService.findAll();

            mv.addObject("companys", companys);
            mv.addObject("companyId", principal.getCompanyId());
            mv.addObject("lines", lines);
            mv.setViewName("zhuanxian/cars");
            return mv;
        } else {
            throw new NoPermissionException();
        }

    }

    @RequestMapping(value = "carsData", method = RequestMethod.GET)
    @ResponseBody
    public Page<Map> carsData(@RequestParam(required = false, value = "company") String companyNames,
                              @RequestParam(required = false, value = "lineName") String lineName,
                              @RequestParam(required = false, value = "carNumber") String carNumber,
                              @RequestParam(required = false, value = "employName") String employName,
                              @RequestParam(required = false, value = "status") Integer[] status) {
        Subject subject = SecurityUtils.getSubject();
        Principal principal = (Principal) subject.getPrincipal();
        String allstatus = "";
        if (status != null && status.length > 0) {
            allstatus = StringUtils.join(status, ",");
        }
        Page<Map> page = null;
        if (principal.isCompanyType()) {
            //总公司
            page = zhuanxianService.queryCarsByParams(null, companyNames, lineName, carNumber, employName, allstatus);
        } else {
            //分公司
            page = zhuanxianService.queryCarsByParams(principal.getCompanyId(), null, lineName, carNumber, employName, allstatus);
        }

        return page;
    }

    private long[] stringArrayToLongArray(String[] strs) {
        if (null == strs) {
            throw new RuntimeException("数组参数异常");
        }
        long[] n = new long[strs.length];
        for (int i = 0; i < strs.length; i++) {
            n[i] = Long.parseLong(strs[i]);
        }
        return n;
    }

    // 保存车辆
    @RequestMapping(value = "createCar", method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> createCar(@RequestParam(value = "companyId", required = false) Long companyId,
                                  @RequestParam(value = "companyName", required = false) String companyName, @RequestParam("carName") String carName,
                                  @RequestParam("carNumber") String carNumber, @RequestParam("lineId") Long[] lineId,
                                  @RequestParam(value = "employId", required = false) Long employId,
                                  @RequestParam(value = "employName", required = false) String employName, @RequestParam("ridepeopleNumber") Integer ridepeopleNumber)
            throws ParseException {
        Subject subject = SecurityUtils.getSubject();
        Principal principal = (Principal) subject.getPrincipal();
        if (subject.isPermitted("zhuanxianCar")) {
            Map<String, Object> car = null;
            if (StringUtils.isNotBlank(carNumber)) {
                carNumber = carNumber.toUpperCase();
            }
            if (principal.isCompanyType()) {
                //主公司
                car = zhuanxianService.createCar(companyId, companyName, carName, carNumber, lineId, employId, employName, ridepeopleNumber);
            } else {
                //分公司
                car = zhuanxianService.createCar(principal.getCompanyId(), principal.getCompanyAbbreviation(), carName, carNumber, lineId, employId,
                        employName, ridepeopleNumber);
            }
            return car;
        } else {
            throw new NoPermissionException();
        }

    }

    // 查询单个车辆
    @RequestMapping(value = "queryCar", method = RequestMethod.GET)
    public @ResponseBody
    Map<String, Object> queryCar(@RequestParam("id") Long id) throws ParseException {
        Subject subject = SecurityUtils.getSubject();
        if (subject.isPermitted("zhuanxian")) {
            Map<String, Object> map = new HashMap<String, Object>();
            Car car = zhuanxianService.findCar(id);

            if (car != null) {

                map.put("success", true);
                map.put("data", car);
            } else {
                map.put("success", false);
                map.put("message", "车辆查询失败");
            }
            return map;
        } else {
            throw new NoPermissionException();
        }

    }

    // 删除单个车辆
    @RequestMapping(value = "deleteCar")
    public @ResponseBody
    Map<String, Object> deleteCar(@RequestParam("id") Long id, @RequestParam(value = "lineId", required = false) Long[] lineId) throws ParseException {
        Subject subject = SecurityUtils.getSubject();
        if (subject.isPermitted("zhuanxian")) {
            Map<String, Object> map = new HashMap<String, Object>();
            List<Order> orders = zhuanxianService.queryRunOrderByCar(id);
            if (CollectionUtils.isNotEmpty(orders)) {
                map.put("message", "该车辆还有正在执行的订单,不能删除");
                map.put("success", false);
                return map;
            }
            map = zhuanxianService.deleteCar(id, lineId);
            return map;
        } else {
            throw new NoPermissionException();
        }

    }

    // 修改车辆
    @RequestMapping(value = "updateCar", method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> updateCar(@RequestParam("carId") Long carId,
                                  @RequestParam(required = false, value = "companyId") Long companyId,
                                  @RequestParam(required = false, value = "companyName") String companyName,
                                  @RequestParam(required = false, value = "carName") String carName, @RequestParam(required =
            false, value = "carNumber") String carNumber,
                                  @RequestParam(required = false, value = "lineId") Long[] lineId, @RequestParam(required =
            false, value = "status") Integer status,
                                  @RequestParam(required = false, value = "employId") Long employId,
                                  @RequestParam(required = false, value = "employName") String employName,
                                  @RequestParam(required = false, value = "ridepeopleNumber") Integer ridepeopleNumber) throws ParseException {
        Subject subject = SecurityUtils.getSubject();
        if (subject.isPermitted("zhuanxianCar")) {
            Map<String, Object> map = new HashMap<String, Object>();
            try {
                if (StringUtils.isNotBlank(carNumber)) {
                    carNumber = carNumber.toUpperCase();
                }
                map = zhuanxianService.updateCar(carId, companyId, companyName, carName, carNumber, lineId, status, employId, employName,
                        ridepeopleNumber);

            } catch (Exception e) {
                e.printStackTrace();
                map.put("success", false);
                map.put("message", "修改失败!");
            }

            return map;
        } else {
            throw new NoPermissionException();
        }
    }

    // 查训线路列表
    @RequestMapping(value = "lines", method = RequestMethod.GET)
    public ModelAndView carTypes() throws ParseException {
        Subject subject = SecurityUtils.getSubject();
        Principal principal = (Principal) subject.getPrincipal();
        ModelAndView mv = new ModelAndView();
        if (subject.isPermitted("zhuanxianLine")) {
            if (principal.isCompanyType()) {
                mv.addObject("companys", companyService.findAll());
            }
            List<Role> roleList = roleService.listByCompanyId(principal.getCompanyId());
            mv.addObject("roles", roleList);
            mv.addObject("companyId", principal.getCompanyId());
            mv.addObject("arealist", areaService.listAll());
            mv.setViewName("zhuanxian/lines");
            return mv;
        } else {
            throw new NoPermissionException();
        }
    }

    @RequestMapping(value = "linesData", method = RequestMethod.GET)
    @ResponseBody
    public Map<String, Object> carTypesData(@RequestParam(required = false, value = "companyName") String companyName) throws ParseException {
        Subject subject = SecurityUtils.getSubject();
        Principal principal = (Principal) subject.getPrincipal();
        if (subject.isPermitted("zhuanxianLine")) {
            Page<Line> page = null;
            if (principal.isCompanyType()) {
                page = zhuanxianService.queryByLineCompany(null, companyName);
            } else {
                page = zhuanxianService.queryByLineCompany(principal.getCompanyId(), null);
            }

            List<Area> areaList = areaService.listAll();
            List<Line> contents = page.getContent();
            for (Line line : contents) {
                boolean areaFlag = false;
                boolean baocheAreaFlag = false;
                boolean jihuoAreaFlag = false;
                // 如果遍历到立即pinche收费标准还存在收费标准列表，终止循环,不改变值(flag=true)
                if (line.getArea() != null) {
                    long areaId = line.getArea().getId();
                    areaFlag = isAreaIdExist(areaList, areaId, areaFlag);
                    // 如果再收费标准列表中未发现pinche收费标准(flage = false)，改变值
                    if (!areaFlag) {
                        line.setArea(null);
                    }
                }
                if (line.getBaocheArea() != null) {
                    // baoche
                    Long baocheAreaId = line.getBaocheArea().getId();
                    baocheAreaFlag = isAreaIdExist(areaList, baocheAreaId, baocheAreaFlag);
                    // baoche
                    if (!baocheAreaFlag) {
                        line.setBaocheArea(null);
                    }
                }
                if (line.getJihuoArea() != null) {
                    // jihuo
                    Long jihuoAreaId = line.getJihuoArea().getId();
                    jihuoAreaFlag = isAreaIdExist(areaList, jihuoAreaId, jihuoAreaFlag);
                    // jihuo
                    if (!jihuoAreaFlag) {
                        line.setJihuoArea(null);
                    }
                }
            }

            Map<String, Object> map = new HashMap<String, Object>();
            map.put("page", page);
            map.put("areaList", areaList);
            return map;
        } else {
            throw new NoPermissionException();
        }
    }

    @RequestMapping(value = "createLine", method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> createCarType(@RequestParam("name") String name, @RequestParam("startCity") String startCity,
                                      @RequestParam("startAddress") String startAddress, @RequestParam("endCity") String endCity,
                                      @RequestParam("endAddress") String endAddress, @RequestParam(required = false, value = "companyId") Long companyId,
                                      @RequestParam(required = false, value = "companyName") String companyName, @RequestParam("jihuoAreaId") Long jihuoAreaId,
                                      @RequestParam("baocheAreaId") Long baocheAreaId, @RequestParam("areaId") Long areaId, @RequestParam(required = false, value = "contactNumber") String contactNumber,
                                      @RequestParam(value = "roleId", required = false) Long[] roleId) throws ParseException {
        Subject subject = SecurityUtils.getSubject();
        Principal principal = (Principal) subject.getPrincipal();
        if (subject.isPermitted("zhuanxianLine")) {
            Map<String, Object> map = new HashMap<String, Object>();
            if (principal.isCompanyType()) {
                map = zhuanxianService.createLine(companyId, companyName, name, startCity, startAddress, endCity, endAddress, areaId, jihuoAreaId, baocheAreaId, contactNumber, roleId);
            } else {
                map = zhuanxianService.createLine(principal.getCompanyId(), principal.getCompanyAbbreviation(), name, startCity, startAddress,
                        endCity, endAddress, areaId, jihuoAreaId, baocheAreaId, contactNumber, roleId);
            }

            return map;
        } else {
            throw new NoPermissionException();
        }

    }

    /**
     * @param companyId
     * @param deleteRepeat 是否去重
     * @return
     * @throws ParseException
     */
    @RequestMapping(value = "queryLines")
    public @ResponseBody
    Map<String, Object> queryLines(
        @RequestParam(required = false, value = "companyId") Long companyId,
        @RequestParam(required = false, value = "deleteRepeat") Integer deleteRepeat)
        throws ParseException {
        Subject subject = SecurityUtils.getSubject();
        Principal principal = (Principal) subject.getPrincipal();
        if (subject.isPermitted("zhuanxianLine")) {
            Map<String, Object> map = new HashMap<String, Object>();
            List<Line> list = new LinkedList<Line>();
            if (principal.isCompanyType()) {
                list = zhuanxianService.queryLines(companyId);
            } else {
                list = zhuanxianService.queryLines(principal.getCompanyId());
            }
            /**去掉重复的逆向线路*/
            if (deleteRepeat != null && deleteRepeat == 1) {
                list = LineUtil.deleteRepreat(list);
            }
            map.put("success", true);
            map.put("company_main", principal.isCompanyType());
            map.put("lines", list);
            return map;
        } else {
            throw new NoPermissionException();
        }

    }

    // 删除线路
    @RequestMapping(value = "deleteLine")
    public @ResponseBody
    Map<String, Object> deleteLine(@RequestParam("id") Long id) throws ParseException {
        Subject subject = SecurityUtils.getSubject();
        Map<String, Object> map = new HashMap<String, Object>();
        if (subject.isPermitted("zhuanxian")) {
            List<Order> list = zhuanxianService.findRunOrderByLineId(id);
            if (CollectionUtils.isNotEmpty(list)) {
                map.put("success", false);
                map.put("message", "该线路还有正在执行的订单,不能删除");
                return map;
            }

            map = zhuanxianService.deleteLine(id);
            return map;
        } else {
            throw new NoPermissionException();
        }

    }

    @RequestMapping(value = "updateLine", method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> updateCarType(@RequestParam("lineId") String id,
                                      @RequestParam(required = false, value = "name") String name, @RequestParam(required = false, value = "startCity") String startCity,
                                      @RequestParam(required = false, value = "startAddress") String startAddress,
                                      @RequestParam(required = false, value = "endCity") String endCity,
                                      @RequestParam(required = false, value = "endAddress") String endAddress,
                                      @RequestParam(required = false, value = "companyId") Long companyId,
                                      @RequestParam(required = false, value = "companyName") String companyName,
                                      @RequestParam(required = false, value = "jihuoAreaId") Long jihuoAreaId,
                                      @RequestParam(required = false, value = "baocheAreaId") Long baocheAreaId,
                                      @RequestParam(required = false, value = "areaId") Long areaId,
                                      @RequestParam(required = false, value = "contactNumber") String contactNumber)
            throws ParseException {
        Subject subject = SecurityUtils.getSubject();
        if (subject.isPermitted("zhuanxianLine")) {
            Map<String, Object> map = zhuanxianService.updateLine(id, companyId, companyName, name, startCity, startAddress, endCity, endAddress,
                    areaId, jihuoAreaId, baocheAreaId, contactNumber);
            return map;
        } else {
            throw new NoPermissionException();
        }
    }

    @RequestMapping("orderList")
    public ModelAndView orderlist() {

        Subject subject = SecurityUtils.getSubject();
        Principal principal = (Principal) subject.getPrincipal();
        if (subject.isPermitted("zhuanxian")) {
            ModelAndView mv = new ModelAndView();
            Company company = companyService.findOne(principal.getCompanyId());
            mv.addObject("lng", company.getLongitude());
            mv.addObject("lat", company.getLatitude());
            List<Line> lines = null;
            if (principal.isCompanyType()) {
                lines = zhuanxianService.queryLines(null);
                mv.addObject("companys", companyService.findAll());
            } else {
                lines = zhuanxianService.queryLines(principal.getCompanyId());
            }
            mv.addObject("lines", lines);
            mv.setViewName("zhuanxian/orderlist");

            return mv;
        } else {
            throw new NoPermissionException();
        }

    }

    @RequestMapping("orderlistData")
    public @ResponseBody
    Page<Map<String, Object>> orderListData(@RequestParam(required = false, value = "orderNumber") String orderNumber,
                                            @RequestParam(required = false, value = "clientPhone") String clientPhone,
                                            @RequestParam(required = false, value = "driverPhone") String driverPhone,
                                            @RequestParam(required = false, value = "companyName") String companyName,
                                            @RequestParam(required = false, value = "startTime") String startTime, @RequestParam(required = false, value = "endTime") String endTime,
                                            @RequestParam(required = false, value = "orderType") String[] orderType,
                                            @RequestParam(required = false, value = "status") Integer[] status, @RequestParam(required = false, value = "page") Integer page,
                                            @RequestParam(required = false, value = "rows") Integer rows, @RequestParam(required = false, value = "treatment") String treatment,
                                            @RequestParam(required = false, value = "startFinishTime") String startFinishTime,
                                            @RequestParam(required = false, value = "endFinishTime") String endFinishTime) throws ParseException {
        Subject subject = SecurityUtils.getSubject();
        Principal principal = (Principal) subject.getPrincipal();
        if (subject.isPermitted("zhuanxian")) {
            String allstatus = "";
            String allorderType = "";
            if (orderType != null) {
                for (int i = 0; i < orderType.length; i++) {
                    allorderType += orderType[i];
                    if (i != orderType.length - 1) {
                        allorderType += ",";
                    }
                }
            }
            if (status != null) {
                for (int i = 0; i < status.length; i++) {
                    allstatus += status[i];
                    if (i != status.length - 1) {
                        allstatus += ",";
                    }
                }
            }
            page = Pager.getPage();
            rows = Pager.getLimit();

            Page<Map<String, Object>> result = null;
            if (principal.isCompanyType()) {
                result = zhuanxianService.orderListData(orderNumber, clientPhone, driverPhone, companyName, startTime, endTime, allorderType,
                        allstatus, page, rows, treatment, startFinishTime, endFinishTime);
            } else {
                result = zhuanxianService.orderListData(orderNumber, clientPhone, driverPhone, null, startTime, endTime, allorderType, allstatus,
                        page, rows, treatment, startFinishTime, endFinishTime);
            }

            return result;
        } else {
            throw new NoPermissionException();
        }
    }

    @RequestMapping(value = "exportOrder", method = RequestMethod.GET)
    public void exportOrder(@RequestParam(required = false, value = "orderNumber") String orderNumber,
                            @RequestParam(required = false, value = "clientPhone") String clientPhone,
                            @RequestParam(required = false, value = "driverPhone") String driverPhone,
                            @RequestParam(required = false, value = "companyName") String companyName,
                            @RequestParam(required = false, value = "startTime") String startTime, @RequestParam(required = false, value = "endTime") String endTime,
                            @RequestParam(required = false, value = "orderType") String[] orderType,
                            @RequestParam(required = false, value = "status") Integer[] status,
                            @RequestParam(required = false, value = "treatment") String treatment,
                            @RequestParam(required = false, value = "startFinishTime") String startFinishTime,
                            @RequestParam(required = false, value = "endFinishTime") String endFinishTime, HttpServletRequest req, HttpServletResponse response)
            throws IOException, ParseException {
        Subject subject = SecurityUtils.getSubject();
        Principal principal = (Principal) subject.getPrincipal();
        if (subject.isPermitted("zhuanxian")) {

            String allstatus = "";
            String allorderType = "";
            if (orderType != null) {
                for (int i = 0; i < orderType.length; i++) {
                    allorderType += orderType[i];
                    if (i != orderType.length - 1) {
                        allorderType += ",";
                    }
                }
            }
            if (status != null) {
                for (int i = 0; i < status.length; i++) {
                    allstatus += status[i];
                    if (i != status.length - 1) {
                        allstatus += ",";
                    }
                }
            }
            List<Map<String, Object>> content = new ArrayList<Map<String, Object>>();
            if (principal.isCompanyType()) {
                content = zhuanxianService.orderListDataExport(orderNumber, clientPhone, driverPhone, companyName, startTime, endTime, allorderType,
                        allstatus, treatment, startFinishTime, endFinishTime);
            } else {
                content = zhuanxianService.orderListDataExport(orderNumber, clientPhone, driverPhone, null, startTime, endTime, allorderType,
                        allstatus, treatment, startFinishTime, endFinishTime);
            }

            List<List<String>> rowlist = new ArrayList<List<String>>();
            String[] head = new String[27];
            head[0] = ("状态");
            head[1] = ("单号");
            head[2] = ("订单类型");
            head[3] = ("下单时间");
            head[4] = ("来源");
            head[5] = ("客户名称");
            head[6] = ("客户电话");
            head[7] = ("使用人电话");
            head[8] = ("预约时间");
            head[9] = ("预约地");
            head[10] = ("目的地");
            head[11] = ("乘坐人数");

            head[12] = ("实收金额");
            head[13] = ("支付方式");
            head[14] = ("预算金额");
            head[15] = ("加收金额");
            head[16] = ("服务人员调价");

            head[17] = ("服务人员名称");
            head[18] = ("服务人员电话");

            head[19] = ("所属公司");

            head[20] = ("线路");
            head[21] = ("车牌号");

            head[22] = ("服务时间");
            head[23] = ("里程");
            head[24] = ("等待时间");
            head[25] = ("备注");
            head[26] = ("销单原因");

            for (Map<String, Object> map : content) {
                List<String> celllist = new ArrayList<String>();
                if (map.get("status").equals(Order.ORDER_STATUS_NEW)) {
                    celllist.add("未派单");
                } else if (map.get("status").equals(Order.ORDER_STATUS_PAIDAN)) {
                    celllist.add("已派单");
                } else if (map.get("status").equals(Order.ORDER_STATUS_JIEDAN) || map.get("status").equals(Order.ORDER_STATUS_ARRIVE)
                        || map.get("status").equals(Order.ORDER_STATUS_ZHIXING)) {
                    celllist.add("已接单");
                } else if (map.get("status").equals(Order.ORDER_STATUS_OK)) {
                    celllist.add("已完成");
                } else if (map.get("status").equals(Order.ORDER_STATUS_XIAODAN)) {
                    celllist.add("已销单");
                }

                celllist.add(map.get("orderNo").toString());
                celllist.add(map.get("orderType").toString());
                celllist.add(map.get("created").toString());
                celllist.add(map.get("channelName").toString());
                celllist.add(map.get("passengerName").toString());
                celllist.add(UseAllDataUtil.useAllData(map.get("passengerPhone").toString()));
                celllist.add(map.get("showPhone").toString());
                celllist.add(map.get("serverTime").toString());

                if (map.get("startAddress") != null && map.get("startAddressDetail") != null) {
                    celllist.add(map.get("startAddress").toString() + "(" + map.get("startAddressDetail").toString() + ")");
                } else if (map.get("startAddress") == null && map.get("startAddressDetail") != null) {
                    celllist.add("(" + map.get("startAddressDetail").toString() + ")");
                } else if (map.get("startAddress") != null && map.get("startAddressDetail") == null) {
                    celllist.add(map.get("startAddress").toString());
                } else {
                    celllist.add("");
                }
                if (map.get("endAddress") != null && map.get("endAddressDetail") != null) {
                    celllist.add(map.get("endAddress").toString() + "(" + map.get("endAddressDetail").toString() + ")");
                } else if (map.get("endAddress") == null && map.get("endAddressDetail") != null) {
                    celllist.add("(" + map.get("endAddressDetail").toString() + ")");
                } else if (map.get("endAddress") != null && map.get("endAddressDetail") == null) {
                    celllist.add(map.get("endAddress").toString());
                } else {
                    celllist.add("");
                }

                celllist.add(map.get("peopleNumber") == null ? "0" : map.get("peopleNumber").toString());

                if (map.get("status").equals(Order.ORDER_STATUS_OK)) {
                    celllist.add(map.get("realPay") == null ? "0元" : map.get("realPay").toString() + "元");
                    celllist.add(map.get("preAndAfterPayType") == null ? "-" : map.get("preAndAfterPayType").toString());
                } else {
                    celllist.add("-");
                    celllist.add("-");
                }
                celllist.add(map.get("budgetPay") == null ? "0元" : map.get("budgetPay").toString() + "元");
                if (map.get("status").equals(Order.ORDER_STATUS_OK)) {
                    celllist.add(("过路费：" + map.get("guoluMoney").toString() + "元，远程费：" + map.get("yuanchengMoney").toString() + "元，其他费：" + map.get(
                            "otherMoney").toString())
                            + "元");
                } else {
                    celllist.add("-");
                }
                celllist.add((null != map.get("justKilometres") ? map.get("justKilometres") + "公里，" : "-，")
                        + (null != map.get("justMoney") ? map.get("justMoney") + "元" : "-"));
                if (map.get("employName") != null) {
                    celllist.add(map.get("employName").toString());
                } else {
                    celllist.add("-");
                }
                if (map.get("employPhone") != null) {
                    celllist.add(UseAllDataUtil.useAllDataDriver(map.get("employPhone").toString()));
                } else {
                    celllist.add("-");
                }

                celllist.add(map.get("companyName").toString());

                celllist.add(map.get("lineName").toString());

                if (map.get("carNumber") != null) {
                    celllist.add(map.get("carNumber").toString());
                } else {
                    celllist.add("-");
                }

                if (map.get("runtime") != null) {
                    celllist.add(map.get("runtime").toString() + "分钟");
                } else {
                    celllist.add("0分钟");
                }
                celllist.add(map.get("mileage") == null ? "0公里" : map.get("mileage").toString() + "公里");
                celllist.add(map.get("startWait") == null ? "0分钟" : map.get("startWait").toString() + "分钟");

                celllist.add(map.get("memoStr") == null ? "-" : map.get("memoStr").toString());
                if (map.get("cancelCause") != null) {
                    celllist.add(map.get("cancelCause").toString());
                } else {
                    celllist.add("-");
                }

                rowlist.add(celllist);
            }

            ExcelUtil.export(req, response, head, rowlist);
        } else {
            throw new NoPermissionException();
        }

    }

    // 根据昵称,工号,电话模糊查询服务人员
    @RequestMapping(value = "getDriver", method = RequestMethod.GET)
    public @ResponseBody
    List<Map<String, Object>> getDriver(String param) {
        List<Driver> drivers = driverService.findByParamLike(param, null);
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        for (Driver driver : drivers) {
            if (driver.getDriverJobType().contains("zhuanxian")) {
                Map<String, Object> map = new HashMap<String, Object>();
                map.put("id", driver.getId());
                map.put("username", driver.getRealname());// 工号
                map.put("phone", driver.getPhone());// 电话
                list.add(map);
            }
        }
        return list;
    }

    /**
     * 销单:
     * controller :权限(zhuanxian)-销单服务-driver状态监测并改变(同步,小)
     * 销单服务:调专线服务器销单(order,orderstatus)-异步专线销单事件
     * 异步专线销单事件:driver状态(所有订单)监测并改变(异步,复杂),推送司机,乘客,短信司机
     *
     * @param id
     * @param cause
     * @return @zhyu
     */
    @RequestMapping(value = "cancel", method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> cancel(@RequestParam("id") Long id, @RequestParam("cause") String cause) {

        Subject subject = SecurityUtils.getSubject();
        Principal principal = (Principal) subject.getPrincipal();

        Map<String, Object> map = new HashMap<String, Object>();

        if (subject.isPermitted("zhuanxian")) {

            Order order = zhuanxianService.findOne(id);
            if (Order.ORDER_STATUS_JIEDAN.equals(order.getStatus())) {
                if (!subject.isPermitted("zhuanxianCancel")) {
                    map.put("success", false);
                    map.put("message", "您没有强制销单权限");
                    return map;
                }
            }
            Result<Order> result = zhuanxianService.cancelOrder(order, cause, principal.getUsername());
            if (result.isSuccess()) {
                map.put("success", true);
                map.put("message", "销单成功");
                if (order.getEmployId() != null) {
                    Driver driver = driverService.findOne(order.getEmployId());
                    if (driver != null) {
                        List<Order> os = zhuanxianService.queryRunOrderByEmploy(driver.getId());
                        if (CollectionUtils.isEmpty(os)) {
                            if (driver.getStatus() != Driver.DRIVER_OFFLINE) {
                                driverService.updateStatusAndJobStatus(Driver.DRIVER_ONLINE, null, driver.getId());
                            }
                        }
                    }

                }
            } else {
                map.put("success", false);
                map.put("message", result.getMessage());
            }
            return map;
        } else {
            map.put("success", false);
            map.put("message", "您没有该权限");
            return map;
        }
    }

    /**
     * 根据距离和时间按照公司的收费标准预估订单价格
     *
     * @param
     * @param
     * @param time
     * @param mileage
     * @return
     */
    @RequestMapping(value = "getBudgetedExpensePrice", method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> getPrice(@RequestParam("areaId") Long areaId, @RequestParam("time") String time,
                                 @RequestParam("mileage") String mileage) {
        Subject subject = SecurityUtils.getSubject();
        if (subject.isPermitted("zhuanxian")) {
            Map<String, Object> result = new HashMap<String, Object>();
            BigDecimal money = BigDecimal.ZERO;
            try {

                Area area = areaService.findOneWithCharge(areaId);
                Long time1 = 0L;
                Double mileage1 = 0.0;
                if (time != null) {
                    Long day = 0L;
                    Long hour = 0L;
                    Long minute = 0L;
                    if (time.contains("天")) {
                        String str1 = time.substring(0, time.indexOf("天"));
                        day = Long.parseLong(str1);
                    }
                    if (time.contains("小时") && time.contains("天")) {
                        String str2 = time.substring(time.indexOf("天") + 1, time.indexOf("小时"));
                        hour = Long.parseLong(str2);
                    } else if (time.contains("小时") && !time.contains("天")) {
                        String str2 = time.substring(0, time.indexOf("小时"));
                        hour = Long.parseLong(str2);
                    }
                    if (time.contains("分钟") && time.contains("小时")) {
                        String str3 = time.substring(time.indexOf("小时") + 2, time.indexOf("分钟"));
                        minute = Long.parseLong(str3);
                    } else if (time.contains("分钟") && !time.contains("小时")) {
                        String str3 = time.substring(0, time.indexOf("分钟"));
                        minute = Long.parseLong(str3);
                    }
                    time1 = (day * 24 * 60) + (hour * 60) + (minute);

                }
                if (mileage != null) {
                    Double leng = 0.0;
                    if (mileage.contains("公里")) {
                        String str1 = mileage.substring(0, mileage.indexOf("公里"));
                        leng = Double.parseDouble(str1);
                    }
                    if (mileage.contains("米")) {
                        String str3 = mileage.substring(0, mileage.indexOf("米"));
                        leng = leng + (Double.parseDouble(str3) / 1000);
                    }
                    mileage1 = leng;
                }

                SelectPrice selectPrice = new SelectPrice();
                selectPrice.setPrice(time1, mileage1, area, null, 0D);

                money = selectPrice.shouldCash;
                BigDecimal startPrice = selectPrice.qbCost;
                BigDecimal mileagePrice = selectPrice.disCost;
                BigDecimal travelTimePrice = selectPrice.travalTimeCost;
                ChargeStartTime price = selectPrice.getPrice();
                StringBuilder builder = new StringBuilder();
                builder.append("起步价:" + startPrice + "元\n");
                List<ChargeStartDistance> distances = price.getChargeStartDistances();

                if (distances != null && distances.size() != 0) {
                    for (ChargeStartDistance d : distances) {
                        builder.append(d.getStartdistance() + "公里到" + d.getDistance() + "公里内,加收" + d.getMoney() + "元");
                        builder.append("\n");
                    }
                }

                builder.append("超过" + price.getQblc() + "公里");
                builder.append("以后每" + price.getDjglUnit() + "公里");
                builder.append("加收" + price.getDjglCost() + "元");
                if (price.getDjglThresholdt() != 0) {
                    builder.append("(不足" + price.getDjglThresholdt() + "公里不计费)");
                }
                builder.append("\n");
                builder.append("起步后" + price.getQbsj() + "分钟内不收费");
                builder.append("以后每" + price.getDjsjUnit() + "分钟");
                builder.append("加收" + price.getDjsjCost() + "元");
                if (price.getDjsjThresholdt() != 0) {
                    builder.append("(不足" + price.getDjsjThresholdt() + "分钟不收费)");
                }
                builder.append("\n");
                builder.append("免费等候" + price.getMfdhsj() + "分钟");
                BigDecimal bigDecimal = price.getDhsjAtonceCost();

                if (bigDecimal.compareTo(BigDecimal.ZERO) == 1) {
                    builder.append("到达则立即加收" + price.getDhsjAtonceCost() + "元");
                }
                builder.append("后每" + price.getDhsjUnit() + "分钟");
                builder.append("加收" + price.getDhsjCost() + "元");
                if (price.getDhsjThresholdt() != 0) {
                    builder.append("(低于" + price.getDhsjThresholdt() + "分钟不计费)");
                }
                builder.append("\n");
                if (StringUtils.isNotBlank(area.getMemo())) {
                    builder.append("备注:" + area.getMemo());
                }
                result.put("success", true);
                result.put("message", "请求成功");
                if (money != null) {
                    money = new BigDecimal(new DecimalFormat("0.0").format(money));
                } else {
                    money = BigDecimal.ZERO;
                }
                result.put("money", money);
                result.put("travelTime", time1); // 执行时间
                result.put("startPrice", startPrice != null ? startPrice : 0.0); // 起步价
                result.put("mileage", mileage1 != null ? mileage1 : 0.0); // 行驶里程
                result.put("mileagePrice", mileagePrice != null ? mileagePrice : 0.0); // 行驶里程费用
                result.put("travelTimePrice", travelTimePrice != null ? travelTimePrice : 0.0); // 服务时间费用
                result.put("areaId", area.getId());
                return result;

            } catch (Exception e) {
                e.printStackTrace();
                result.put("success", false);
                result.put("message", "请求失败");
                return result;
            }

        } else {
            throw new NoPermissionException();
        }
    }

    /**
     * 根据距离和时间按照公司的收费标准预估订单价格
     *
     * @return
     */
    @RequestMapping(value = "getPrice", method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> getPrice(@RequestParam("lineId") Long lineId) {
        Subject subject = SecurityUtils.getSubject();
        if (subject.isPermitted("zhuanxian")) {
            Map<String, Object> result = new HashMap<String, Object>();
            BigDecimal money = BigDecimal.ZERO;
            try {
                if (lineId == null) {
                    throw new RuntimeException("参数错误");
                }
                Line line = zhuanxianService.findByLine(lineId);

                Area area = areaService.findOneWithCharge(line != null ? line.getAreaId() : null);
                if (area == null) {
                    throw new RuntimeException("城际专线收费标准为空");
                }
                Area baocheArea = areaService.findOneWithCharge(line != null ? line.getBaocheAreaId() : null);
                Area jihuoArea = areaService.findOneWithCharge(line != null ? line.getJihuoAreaId() : null);
                Long time1 = 0L;
                Double mileage1 = 0.0;

                SelectPrice selectPrice = new SelectPrice();
                selectPrice.setPrice(time1, mileage1, area, null, 0D);

                SelectPrice baocheAreaPrice = new SelectPrice();
                baocheAreaPrice.setPrice(time1, mileage1, baocheArea, null, 0D);

                SelectPrice jihuoAreaPrice = new SelectPrice();
                jihuoAreaPrice.setPrice(time1, mileage1, jihuoArea, null, 0D);

                money = selectPrice.shouldCash;
                BigDecimal startPrice = selectPrice.qbCost;
                BigDecimal mileagePrice = selectPrice.disCost;
                BigDecimal travelTimePrice = selectPrice.travalTimeCost;
                ChargeStartTime price = selectPrice.getPrice();
                StringBuilder builder = new StringBuilder();
                builder.append("起步价:" + startPrice + "元\n");
                List<ChargeStartDistance> distances = price.getChargeStartDistances();

                if (distances != null && distances.size() != 0) {
                    for (ChargeStartDistance d : distances) {
                        builder.append(d.getStartdistance() + "公里到" + d.getDistance() + "公里内,加收" + d.getMoney() + "元");
                        builder.append("\n");
                    }
                }

                builder.append("超过" + price.getQblc() + "公里");
                builder.append("以后每" + price.getDjglUnit() + "公里");
                builder.append("加收" + price.getDjglCost() + "元");
                if (price.getDjglThresholdt() != 0) {
                    builder.append("(不足" + price.getDjglThresholdt() + "公里不计费)");
                }
                builder.append("\n");
                builder.append("起步后" + price.getQbsj() + "分钟内不收费");
                builder.append("以后每" + price.getDjsjUnit() + "分钟");
                builder.append("加收" + price.getDjsjCost() + "元");
                if (price.getDjsjThresholdt() != 0) {
                    builder.append("(不足" + price.getDjsjThresholdt() + "分钟不收费)");
                }
                builder.append("\n");
                builder.append("免费等候" + price.getMfdhsj() + "分钟");
                BigDecimal bigDecimal = price.getDhsjAtonceCost();

                if (bigDecimal.compareTo(BigDecimal.ZERO) == 1) {
                    builder.append("到达则立即加收" + price.getDhsjAtonceCost() + "元");
                }
                builder.append("后每" + price.getDhsjUnit() + "分钟");
                builder.append("加收" + price.getDhsjCost() + "元");
                if (price.getDhsjThresholdt() != 0) {
                    builder.append("(低于" + price.getDhsjThresholdt() + "分钟不计费)");
                }
                builder.append("\n");
                if (StringUtils.isNotBlank(area.getMemo())) {
                    builder.append("备注:" + area.getMemo());
                }
                result.put("success", true);
                result.put("message", "请求成功");
                if (money != null) {
                    money = new BigDecimal(new DecimalFormat("0.0").format(money));
                } else {
                    money = BigDecimal.ZERO;
                }
                result.put("money", money);
                result.put("baocheMoney", baocheAreaPrice.shouldCash);
                result.put("jihuoMoney", jihuoAreaPrice.shouldCash);
                result.put("travelTime", time1); // 执行时间
                result.put("startPrice", startPrice != null ? startPrice : 0.0); // 起步价
                result.put("mileage", mileage1 != null ? mileage1 : 0.0); // 行驶里程
                result.put("mileagePrice", mileagePrice != null ? mileagePrice : 0.0); // 行驶里程费用
                result.put("travelTimePrice", travelTimePrice != null ? travelTimePrice : 0.0); // 服务时间费用
                return result;

            } catch (Exception e) {
                e.printStackTrace();
                result.put("success", false);
                result.put("message", "请求失败");
                return result;
            }

        } else {
            throw new NoPermissionException();
        }
    }

    @RequestMapping(value = "createOrder", method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> create(@RequestParam("orderType") Integer orderType,
        @RequestParam(required = false, value = "peopleNumber") Long peopleNumber,
        @RequestParam(required = false, value = "passengerId") Long passengerId,
        @RequestParam(required = false, value = "passengerName") String passengerName,
        @RequestParam("passengerPhone") String passengerPhone,
        @RequestParam(required = false, value = "companyId") Long companyId,
        @RequestParam(required = false, value = "companyName") String companyName,
        @RequestParam("lineId") Long lineId,
        @RequestParam("startAddress") String startAddress,
        @RequestParam("startLat") Double startLat, @RequestParam("startLng") Double startLng,
        @RequestParam("endAddress") String endAddress, @RequestParam("endLat") Double endLat,
        @RequestParam("endLng") Double endLng,
        @RequestParam("startTime") String startTime,
        @RequestParam(required = false, value = "budgetPay") Double budgetPay,
        @RequestParam(required = false, value = "startPrice") Double startPrice,
        @RequestParam(required = false, value = "mileagePrice") Double mileagePrice,
        @RequestParam(required = false, value = "runTimePrice") Double runTimePrice,
        @RequestParam(required = false, value = "travelTime") Integer travelTime,
        @RequestParam(required = false, value = "mileage") Double mileage,
        @RequestParam(required = false, value = "memo") String memo,
        @RequestParam(required = false, value = "takeDeliveryName") String takeDeliveryName,
        @RequestParam(required = false, value = "takeDeliveryPhone") String takeDeliveryPhone,
        @RequestParam(required = false, value = "employId") Long[] employId,
        @RequestParam(required = false, value = "couponId") Long couponId)
        throws ParseException {
        Subject subject = SecurityUtils.getSubject();
        Map<String, Object> result = new HashMap<String, Object>();
        Principal principal = (Principal) subject.getPrincipal();
        if (companyId == null || companyId == 0 || !principal.isCompanyType()) {
            companyId = principal.getCompanyId();
        }
        if (StringUtils.isBlank(companyName) || !principal.isCompanyType()) {
            companyName = principal.getCompanyAbbreviation();
        }
        if (subject.isPermitted("zhuanxian")) {
            try {

                String channelName = Order.ORDER_TYPE_PHONE;

                Date serverDate = DateUtils.parseDate(startTime, "yyyy-MM-dd HH:mm");
                passengerPhone = passengerPhone.replaceAll(" ", "").replaceAll("-", "");
                Result<List<Order>> r = zhuanxianService
                    .createOrder(orderType, peopleNumber, passengerId, passengerName,
                        passengerPhone, companyId,
                        companyName, lineId, startAddress, startLat, startLng, endAddress, endLat,
                        endLng, serverDate, budgetPay, startPrice,
                        mileagePrice, runTimePrice, travelTime, mileage, channelName, couponId,
                        takeDeliveryName, takeDeliveryPhone,
                        principal.getUsername(), memo);

                if (r.isSuccess()) {
                    String message = "下单成功!";

                    if (couponId != null) {
                        Coupon coupon = couponService.findOne(couponId);
                        coupon.setStatus(Coupon.COUPON_STATUS_HASUSED);
                        couponService.update(coupon);
                    }

                    if (null == passengerId) {
                        Passenger passenger = memberService.findOnePassengerByPhone(passengerPhone);
                        if (null != passenger) {
                            // 新注册活动
                            ReactorVo rVo = new ReactorVo();
                            rVo.setPassenger(passenger);
                            rVo.setActivityEvent(ActivityEvent.newRegister);
                            ActivityCheckEvent activityCheckEvent = new ActivityCheckEvent(rVo);
                            applicationEventMulticaster.multicastEvent(activityCheckEvent);
                        }
                    }

                    List<Order> orders = r.getResult();
                    for (Order order : orders) {
                        String detail = "【%s】新增城际专线订单【" + order.getOrderNo() + "】";

                        OperationLogEvent operationLogEvent = new OperationLogEvent(principal, detail);
                        applicationEventMulticaster.multicastEvent(operationLogEvent);
                        // 推送和记录 参考队列
                    }
                    List<Order> paidanOrder = new ArrayList<Order>();
                    List<Order> newOrders = new ArrayList<Order>();
                    if (employId != null && employId.length > 0) {
                        for (int i = 0; i < employId.length; i++) {
                            Long empId = employId[i];
                            Map<String, Object> map = getDriverBusy(empId);
                            Boolean kongxian = (Boolean) map.get("success");
                            if (!kongxian) {
                                String msg = (String) map.get("message");
                                message += msg;
                            } else {
                                Map<String, Object> paidanMap = this.paidan(empId, orders.get(i).getId());
                                if ((boolean) paidanMap.get("success")) {
                                    ZhuanxianOrderRecordEvent recordEvent = new ZhuanxianOrderRecordEvent(orders.get(i).getId());
                                    applicationEventMulticaster.multicastEvent(recordEvent);
                                    paidanOrder.add(orders.get(i));
                                }
                            }
                        }
                        for (Order o1 : orders) {
                            boolean flag = true;
                            for (Order o2 : paidanOrder) {
                                if (o1.getId().equals(o2.getId())) {
                                    flag = false;
                                    break;
                                }
                            }
                            if (flag) {
                                newOrders.add(o1);
                            }
                        }

                    } else {
                        newOrders.addAll(orders);
                    }
                    for (Order o : newOrders) {
                        ZhuanxianOrderCreateEvent createEvent = new ZhuanxianOrderCreateEvent(o.getId());
                        applicationEventMulticaster.multicastEvent(createEvent);
                        ZhuanxianOrderRecordEvent recordEvent = new ZhuanxianOrderRecordEvent(o.getId());
                        applicationEventMulticaster.multicastEvent(recordEvent);
                    }

                    result.put("success", true);
                    result.put("message", message);

                } else {
                    result.put("success", false);
                    result.put("message", r.getMessage());
                }

            } catch (Exception e) {
                result.put("success", false);
                result.put("message", e.getMessage());
            }

            return result;

        } else {
            throw new NoPermissionException();
        }
    }

    // 备注
    @RequestMapping(value = "remark", method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> remark(Long id,
        @RequestParam(required = false, value = "memo") String memo) {
        Subject subject = SecurityUtils.getSubject();
        if (subject.isPermitted("zhuanxian")) {
            Map<String, Object> result = new HashMap<String, Object>();
            Order order = zhuanxianService.findOne(id);
            if (order != null) {
                try {
                    zhuanxianService.remark(id, memo);
                    result.put("success", true);
                    result.put("message", "备注成功");
                } catch (Exception e) {
                    result.put("success", false);
                    result.put("message", "备注失败");
                }

            } else {
                result.put("success", false);
                result.put("message", "订单不存在");
            }
            return result;
        } else {
            throw new NoPermissionException();
        }
    }

    // 根据车辆id查询路线
    @RequestMapping(value = "getLinesByCar", method = RequestMethod.GET)
    public @ResponseBody
    List<Line> getLinesByCar(@RequestParam(required = true, value = "carId") Long carId) {

        return zhuanxianService.getLinesByCar(carId);
    }

    @RequestMapping("zhuanxianMemberOrderData")
    public @ResponseBody
    PageVo<MemberOrderVo> zhuanMemberOrderData(
        @RequestParam(required = false, value = "type") Integer type,
        @RequestParam(required = false, value = "gradeId") Long gradeId,
        @RequestParam(required = false, value = "startTime") String startTime,
        @RequestParam(required = false, value = "endTime") String endTime,
        @RequestParam(required = false, value = "companyId") Long companyId) {

        Subject subject = SecurityUtils.getSubject();
        Principal principal = (Principal) subject.getPrincipal();
        if (subject.isPermitted("zhuanxian")) {
            Date start = null;
            Date end = null;

            if (!StringUtils.isEmpty(startTime)) {

                try {
                    start = DateUtils.parseDate(startTime, "yyyy-MM-dd HH:mm");
                } catch (ParseException e) {
                    e.printStackTrace();
                }

            }

            if (!StringUtils.isBlank(endTime)) {

                try {
                    end = DateUtils.parseDate(endTime, "yyyy-MM-dd HH:mm");
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }

            PageVo<MemberOrderVo> result = null;
            if (principal.isCompanyType()) {
                result = zhuanxianService.zhuanxianMemberOrder(start, end, companyId, gradeId, type);
            } else {
                result = zhuanxianService.zhuanxianMemberOrder(start, end, principal.getCompanyId(), gradeId, type);
            }

            return result;
        } else {
            throw new NoPermissionException();
        }

    }

    /**
     * 收回订单
     *
     * @param id
     * @param cause
     * @return
     */
    @RequestMapping(value = "callback", method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> callback(Long id, String cause) {

        Map<String, Object> map = new HashMap<String, Object>();

        Subject subject = SecurityUtils.getSubject();
        if (subject.isPermitted("zhuanxianCallback")) {

            Order order = zhuanxianService.findOne(id);

            if (order.getStatus().equals(Order.ORDER_STATUS_NEW) || order.getStatus().equals(Order.ORDER_STATUS_PAIDAN)
                    || order.getStatus().equals(Order.ORDER_STATUS_JIEDAN) || order.getStatus().equals(Order.ORDER_STATUS_ARRIVE)) {

                if (order.getTreatment()) {
                    map.put("success", false);
                    map.put("message", "订单已确认，不能收回");
                    return map;
                }

                Driver driver = driverService.findOne(order.getEmployId());

                Result<Order> result = zhuanxianService.callback(id, driver, cause);

                map.put("success", false);
                if (result.isSuccess()) {
                    if (null != driver) {
                        List<Order> os = zhuanxianService.queryRunOrderByEmploy(driver.getId());
                        if (CollectionUtils.isEmpty(os)) {
                            if (driver.getStatus() != Driver.DRIVER_OFFLINE) {
                                driverService.updateStatusAndJobStatus(Driver.DRIVER_ONLINE, null, driver.getId());
                            }
                        }

                        ZhuanxianOrderCallBackEvent callBackEvent = new ZhuanxianOrderCallBackEvent(order, driver);
                        applicationEventMulticaster.multicastEvent(callBackEvent);
                    }
                    map.put("success", true);
                    return map;
                } else {
                    map.put("success", false);
                    map.put("message", result.getMessage());
                    return map;
                }
            } else {
                map.put("success", false);
                map.put("message", "当前订单状态不能回收");
                return map;
            }

        } else {
            map.put("success", false);
            map.put("message", "您没有该权限");
            return map;
        }
    }

    @RequestMapping("detail/{orderId}")
    public ModelAndView detail(@PathVariable("orderId") Long orderId) {
        Subject subject = SecurityUtils.getSubject();
        Principal principal = (Principal) subject.getPrincipal();
        if (subject.isPermitted("zhuanxian")) {
            ModelAndView mv = new ModelAndView();
            Order order = zhuanxianService.findOne(orderId);
            order.setPassengerPhone(UseAllDataUtil.useAllData(order.getPassengerPhone()));
            order.setEmployPhone(UseAllDataUtil.useAllDataDriver(order.getEmployPhone()));
            order.setShowPhone((UseAllDataUtil.useAllDataDriver(StringUtils.isNotBlank(order.getShowPhone()) ? order.getShowPhone() : order
                    .getPassengerPhone())));

            // //////////////////////////////////////////////微信V5新加////////////////////////////////////////////////////

            // 过滤评价标签
            OrderReview review = order.getOrderReview();
            if (null != review) {
                String reviewContent = review.getContent(); // 评价内容
                String subText = "&*&"; // 这是标签与评价内容的分隔符
                String tagText = "&|&"; // 这是标签的分隔符
                String realReview = null;
                if (null != reviewContent) {

                    // 用户输入的评价，过滤掉了标签
                    String realContent = null; // 评价
                    String realTag = null;
                    if (reviewContent.contains(subText)) {
                        realContent = reviewContent.substring(reviewContent.lastIndexOf(subText) + 3, reviewContent.length());
                        realTag = reviewContent.substring(0, reviewContent.lastIndexOf(subText));
                    } else if (reviewContent.contains(tagText)) {
                        realTag = reviewContent;
                        realContent = "";
                    } else {
                        realContent = reviewContent;
                    }

                    // 没有标签，没有评价
                    if (null == realTag && (null == realContent || realContent.isEmpty())) {
                        realReview = "";
                    }

                    // 有标签，没有评价/有评价，将标签变为【标签】的形式
                    if (null != realTag) {
                        String[] tags = realTag.split(tagText);
                        StringBuffer bf = new StringBuffer();
                        for (String tag : tags) {
                            if ("|".equals(tag)) {
                                continue;
                            }
                            if (null != tag && !tag.isEmpty()) {
                                bf.append("【" + tag + "】 ");
                            }
                        }
                        realReview = (bf.toString() + realContent);
                    }

                    // 没有标签，有评价
                    if (null == realTag && null != realContent) {
                        realReview = realContent;
                    }
                }
                review.setContent(realReview);
                order.setOrderReview(review);
            }

            // //////////////////////////////////////////////////////////////////////////////////////////////////

            mv.addObject("order", order);
//            System.out.println("preAndAfterPayType:"+order.getPreAndAfterPayType());
//            System.out.println("preAndAfterPayMoney:"+order.getPreAndAfterPayMoney());
            mv.addObject("treatment", order.getTreatment());
            mv.addObject("cancel", order.getStatus() == 6 ? true : false);

            List<com.ybkj.daijia.server.zhuanxian.OrderStatus> list = order.getStatusList();

            SimpleDateFormat formart = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            mv.addObject("createDate", formart.format(order.getCreated()));

            for (OrderStatus orderStatus : list) {
                if (order.getStatus() != 6) {
                    if (orderStatus.getStatus() == 2) {// 接单记录
                        mv.addObject("jiedanDate", formart.format(orderStatus.getCreated()));
                    }
                    if (orderStatus.getStatus() == 4) {// 开始服务记录
                        mv.addObject("runDate", formart.format(orderStatus.getCreated()));
                    }
                    if (orderStatus.getStatus() == 4 && order.getTreatment()) {// 确认费用时间
                        mv.addObject("treatmentDate",
                                formart.format(order.getTreatmentDate() != null ? order.getTreatmentDate() : orderStatus.getCreated()));
                    }
                    if (orderStatus.getStatus() == 5) {
                        mv.addObject("finishDate", formart.format(order.getFinishTime() != null ? order.getFinishTime() : orderStatus.getCreated()));
                    }
                } else {
                    if (orderStatus.getStatus() == 2) {// 接单记录
                        mv.addObject("jiedanDate", formart.format(orderStatus.getCreated()));
                    }
                    if (orderStatus.getStatus() == 3 || orderStatus.getStatus() == 4) {// 开始服务记录
                        mv.addObject("runDate", formart.format(orderStatus.getCreated()));
                    }
                }
            }
            for (int i = 0; i < list.size(); i++) {
                if (list.get(i).getStatus() == 6) {
                    order.setStatus(list.get(i - 1).getStatus());
                }
            }
            mv.addObject("username", principal.getUsername());
            mv.setViewName("zhuanxian/detail");
            return mv;
        } else {
            throw new NoPermissionException();
        }
    }

    /**
     * 派单
     *
     * @param driverId
     * @param orderId
     * @return
     */
    @RequestMapping(value = "paidan", method = RequestMethod.POST)
    public synchronized @ResponseBody
    Map<String, Object> paidan(Long driverId, Long orderId) {
        Subject subject = SecurityUtils.getSubject();
        Principal principal = (Principal) subject.getPrincipal();
        Map<String, Object> map = new HashMap<String, Object>();

        if (subject.isPermitted("zhuanxian")) {
            map.put("success", true);
            Driver driver = driverService.findOne(driverId);
            if (driver.getStatus().equals(Driver.DRIVER_OFFLINE)) {
                map.put("success", false);
                map.put("message", "该服务人员状态离线，不能派单");
                return map;
            }

            if (null != driver.getJobStatus() && !driver.getJobStatus().equals(Driver.DRIVER_JOBSTATUS_ZHUANXIAN)) {
                map.put("success", false);
                map.put("message", "该服务人员当前业务状态错误，不能派单");
                return map;
            }
            Order order = zhuanxianService.findOne(orderId);
            if (!Order.ORDER_STATUS_NEW.equals(order.getStatus())) {
                map.put("success", false);
                map.put("message", "订单状态错误，不能派单");
                return map;
            }
            if (driver.getZhuanxianCarId() != null) {
                Car car = zhuanxianService.findCar(driver.getZhuanxianCarId());
                if (car == null) {
                    map.put("success", false);
                    map.put("message", "该服务人员没有专线车辆，不能派单");
                    return map;
                }
                if (car.getLines() == null) {
                    map.put("success", false);
                    map.put("message", "该服务人员的车辆没有指定线路");
                    return map;
                } else {
                    boolean flag = true;
                    for (Line line : car.getLines()) {
                        if (line.getId().equals(order.getLineId())) {
                            flag = false;
                            break;
                        }
                    }
                    if (flag) {
                        map.put("success", false);
                        map.put("message", "该服务人员指定的线路和订单所需线路不一致");
                    }
                }
            } else {
                map.put("success", false);
                map.put("message", "该服务人员没有专线车辆，不能派单");
                return map;
            }

            if (!driver.getDriverJobType().contains(Driver.DriverJobType.zhuanxian.toString())) {
                map.put("success", false);
                map.put("message", "该服务人员不能派专线订单");
                return map;
            }

            Map<String, Object> map2 = getDriverBusy(driver.getId());
            Boolean success = (Boolean) map2.get("success");
            if (!success) {
                return map2;
            }
            Result<Order> result = zhuanxianService.paidan(driver, order);
            if (result.isSuccess()) {
                map.put("success", true);
                String detail = "【%s】派专线单【" + order.getOrderNo() + "】";
                ZhuanxianOrderPaidanEvent paidanEvent = new ZhuanxianOrderPaidanEvent(order);
                applicationEventMulticaster.multicastEvent(paidanEvent);
                OperationLogEvent operationLogEvent = new OperationLogEvent(principal, detail);
                applicationEventMulticaster.multicastEvent(operationLogEvent);
            } else {
                map.put("success", false);
                map.put("message", result.getMessage());
            }
            return map;
        } else {
            map.put("success", false);
            map.put("message", "您没有该权限");
            return map;
        }
    }

    /**
     * 判断司机状态
     *
     * @param employId
     * @return
     */
    public Map<String, Object> getDriverBusy(Long employId) {
        Map<String, Object> map = new HashMap<String, Object>();
        Boolean kongxian = true;
        String message = "";
        Integer code = 0;

        try {
            Driver driver = driverService.findOne(employId);
            ServiceSetting serviceSetting = ServiceUtil.checkOpen();
            if (serviceSetting.isDaijia()) {
                Long daijiaAmount = orderService.countActivedOrdersByDriver(employId);
                if (daijiaAmount > 0) {
                    System.err.println(driver.getRealname() + "还有未完成的代驾工单,不能派单");
                    kongxian = false;
                    message = "还有未完成的代驾工单,不能派单";
                    code = -1;
                }
            }

            if (serviceSetting.isZhuanche()) {
                Long zhuancheAmount = zhuancheService.countActivedOrdersByDriver(employId);
                if (zhuancheAmount > 0) {
                    System.err.println(driver.getRealname() + "还有未完成的专车工单,不能派单");
                    kongxian = false;
                    message = "还有未完成的专车工单,不能派单";
                    code = -2;
                }
            }

            if (serviceSetting.isPaotui()) {
                Long paotuiAmount = errandService.countBusyAmount(employId);
                if (paotuiAmount > 0) {
                    System.err.println(driver.getRealname() + "还有未完成的跑腿工单,不能派单");
                    kongxian = false;
                    message = "还有未完成的跑腿工单,不能派单";
                    code = -3;
                }
            }

            if (serviceSetting.isFreight()) {
                Long huoyunAmount = freightService.countActivedOrdersByDriver(employId);
                if (huoyunAmount > 0) {
                    System.err.println(driver.getRealname() + "还有未完成的货运工单,不能派单");
                    kongxian = false;
                    message = "还有未完成的货运工单,不能派单";
                    code = -4;
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        map.put("success", kongxian);
        map.put("message", message);
        map.put("code", code);
        return map;
    }

    // 获取附近服务人员
    @RequestMapping(value = "getEmployees", method = RequestMethod.GET)
    public @ResponseBody
    List<Map<String, Object>> getEmployees(@RequestParam("lineId") Long lineId,
        @RequestParam("orderType") Integer orderType,
        @RequestParam("startLat") Double startLat, @RequestParam("startLng") Double startLng,
        @RequestParam(required = false, value = "peopleNumber") Long peopleNumber,
        @RequestParam("serverTime") String serverdate)
        throws ParseException {
        Subject subject = SecurityUtils.getSubject();
        if (subject.isPermitted("zhuanxian")) {
            Setting setting = settingUtils.get();
            List<Map<String, Object>> listMap = new ArrayList<Map<String, Object>>();
            List<Car> cars = zhuanxianService.findCarByLine(lineId);

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");

            Date date = sdf.parse(serverdate);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.add(Calendar.MINUTE, -setting.getBookTimeZhuanxian());
            Date serverTime = calendar.getTime();
            if (setting.getBookTimeZhuanxian() > 0) {
                if (serverTime.getTime() < System.currentTimeMillis()) {

                    if (CollectionUtils.isNotEmpty(cars)) {
                        for (Car car : cars) {
                            Map<String, Object> map = new HashMap<String, Object>();
                            if (car.getEmployId() == null) {
                                continue;
                            }
                            Driver driver = driverService.findOne(car.getEmployId());
                            if (driver == null || !driver.getDriverJobType().contains("zhuanxian")
                                    || driver.getStatus().equals(Driver.DRIVER_OFFLINE)) {
                                continue;
                            }
                            Map<String, Object> map2 = getDriverBusy(driver.getId());
                            if (!(boolean) map2.get("success")) {
                                continue;
                            }
                            boolean success = zhuanxianService.isReceiveAnOrder(peopleNumber, orderType, driver.getId());
                            if (!success) {
                                continue;
                            }
                            map.put("employId", driver.getId());
                            map.put("employName", driver.getRealname());
                            map.put("carNumber", car.getCarNumber());
                            map.put("grade", driver.getDriverGrade() == null ? -1 : driver.getDriverGrade().getGrade());
                            DecimalFormat df = new DecimalFormat("#.00");
                            double distance;
                            if (driver.getLastLatitude() != null && driver.getLastLongitude() != null) {
                                distance = Distance.doubleVal(startLat, startLng, driver.getLastLatitude(), driver.getLastLongitude());
                            } else {
                                distance = Distance.doubleVal(startLat, startLng, driver.getLatitude(), driver.getLongitude());
                            }
                            map.put("distance", Double.valueOf(df.format(distance)));
                            listMap.add(map);
                        }
                    }

                } else {
                    if (CollectionUtils.isNotEmpty(cars)) {
                        for (Car car : cars) {
                            Map<String, Object> map = new HashMap(5);
                            if (car.getEmployId() == null) {
                                continue;
                            }
                            Driver driver = driverService.findOne(car.getEmployId());
                            if (driver == null || !driver.getDriverJobType().contains("zhuanxian")
                                    || driver.getStatus().equals(Driver.DRIVER_OFFLINE)) {
                                continue;
                            }
                            Map<String, Object> map2 = getDriverBusy(driver.getId());
                            if (!(boolean) map2.get("success")) {
                                continue;
                            }
                            map.put("employId", driver.getId());
                            map.put("employName", driver.getRealname());
                            map.put("carNumber", car.getCarNumber());
                            map.put("grade", driver.getDriverGrade() == null ? -1 : driver.getDriverGrade().getGrade());
                            DecimalFormat df = new DecimalFormat("#.00");
                            double distance = 0.0;
                            if (driver.getLatitude() == null || driver.getLongitude() == null) {
                                distance = Distance.doubleVal(startLat, startLng, driver.getLastLatitude(), driver.getLastLongitude());
                            } else if (driver.getLastLatitude() == null || driver.getLastLongitude() == null) {
                                distance = Distance.doubleVal(startLat, startLng, driver.getLatitude(), driver.getLongitude());
                            }
                            map.put("distance", Double.valueOf(df.format(distance)));
                            listMap.add(map);
                        }
                    }
                }
            } else {
                if (CollectionUtils.isNotEmpty(cars)) {
                    for (Car car : cars) {
                        Map<String, Object> map = new HashMap<String, Object>();
                        if (car.getEmployId() == null) {
                            continue;
                        }
                        Driver driver = driverService.findOne(car.getEmployId());
                        if (driver == null || !driver.getDriverJobType().contains("zhuanxian") || driver.getStatus().equals(Driver.DRIVER_OFFLINE)) {
                            continue;
                        }
                        Map<String, Object> map2 = getDriverBusy(driver.getId());
                        if (!(boolean) map2.get("success")) {
                            continue;
                        }
                        boolean success = zhuanxianService.isReceiveAnOrder(peopleNumber, orderType, driver.getId());
                        if (!success) {
                            continue;
                        }
                        map.put("employId", driver.getId());
                        map.put("employName", driver.getRealname());
                        map.put("carNumber", car.getCarNumber());
                        map.put("grade", driver.getDriverGrade() == null ? -1 : driver.getDriverGrade().getGrade());
                        DecimalFormat df = new DecimalFormat("#.00");
                        double distance = 0.0;
                        if (driver.getLastLatitude() != null && driver.getLastLongitude() != null) {
                            distance = Distance.doubleVal(startLat, startLng, driver.getLastLatitude(), driver.getLastLongitude());
                        } else {
                            distance = Distance.doubleVal(startLat, startLng, driver.getLatitude(), driver.getLongitude());
                        }
                        map.put("distance", Double.valueOf(df.format(distance)));
                        listMap.add(map);
                    }
                }
            }

            Collections.sort(listMap, new DriverSortGrade());
            return listMap;
        } else {
            throw new NoPermissionException();
        }
    }

    @RequestMapping(value = "zhuanxianHeatMapData", method = RequestMethod.POST)
    public @ResponseBody
    List<PointVo> zhuanxianHeatMapData(@RequestParam(required = false, value = "year") Integer year,
                                       @RequestParam(required = false, value = "month") Integer month) {

        Subject subject = SecurityUtils.getSubject();
        if (subject.isPermitted("zhuanxian")) {
            Calendar calendar = Calendar.getInstance();

            if (null == year) {
                year = calendar.get(Calendar.YEAR);
            }
            if (null == month) {
                month = calendar.get(Calendar.MONTH);
            }

            List<Order> list = zhuanxianService.findMonthOrder(year, month);
            List<Order> matched = new LinkedList<Order>();
            List<PointVo> processed = new LinkedList<PointVo>();

            for (int i = 0; i < list.size(); i++) {

                Order order = list.get(i);

                if (matched.contains(order)) {
                    continue;
                }

                PointVo pointVo = new PointVo();
                if (order.getStartLat() != null && order.getStartLng() != null) {
                    pointVo.lat = order.getStartLat();
                    pointVo.lng = order.getStartLng();
                }

                pointVo.count = 1;
                processed.add(pointVo);

                for (int j = i + 1; j < list.size(); j++) {

                    Order order2 = list.get(j);

                    if (matched.contains(order2)) {
                        continue;
                    }

                    PointVo pointVo2 = new PointVo();
                    if (order2.getStartLat() != null && order2.getStartLng() != null) {
                        pointVo2.lat = order2.getStartLat();
                        pointVo2.lng = order2.getStartLng();
                    }
                    if (pointVo.isSameLocation(pointVo, pointVo2)) { // 相同位置
                        pointVo.count++;
                        matched.add(order2);// 加入已匹配列表
                    }

                }

            }

            return processed;
        } else {
            throw new NoPermissionException();
        }

    }

    @RequestMapping("exportzhuanxianMemberOrder")
    public void exportMemberOrder(
        @RequestParam(required = false, value = "companyId") Long companyId,
        @RequestParam(required = false, value = "startTime") String startTime,
        @RequestParam(required = false, value = "endTime") String endTime,
        @RequestParam(required = false, value = "type") Integer type,
        @RequestParam(required = false, value = "gradeId") Long gradeId,
        HttpServletRequest req, HttpServletResponse response) throws IOException {
        Subject subject = SecurityUtils.getSubject();

        if (subject.isPermitted("zhuanxian")) {
            Date start = null;
            Date end = null;
            if (!StringUtils.isEmpty(startTime)) {

                try {
                    start = DateUtils.parseDate(startTime, "yyyy-MM-dd HH:mm");
                } catch (ParseException e) {
                    e.printStackTrace();
                }

            }

            if (!StringUtils.isBlank(endTime)) {

                try {
                    end = DateUtils.parseDate(endTime, "yyyy-MM-dd HH:mm");
                } catch (ParseException e) {
                    e.printStackTrace();
                }

            }

            PageVo<MemberOrderVo> list = zhuanxianService
                .zhuanxianMemberOrder(start, end, companyId, gradeId, type);

            String[] head = new String[4];
            List<List<String>> rowlist = new ArrayList<List<String>>();

            head[0] = ("客户");
            head[1] = ("所属公司");
            head[2] = ("订单完成数量（单）");
            head[3] = ("订单完成金额（元）");
            for (MemberOrderVo a : list.getContent()) {
                List<String> celllist = new ArrayList<String>();

                celllist.add(a.getName() + "-" + a.getPhone());
                celllist.add(a.getCompanyName());
                celllist.add(a.getFinishNums() + "");
                celllist.add(a.getMoney().setScale(2, BigDecimal.ROUND_HALF_UP).toString());

                rowlist.add(celllist);

            }

            ExcelUtil.export(req, response, head, rowlist);
        } else {
            throw new NoPermissionException();
        }

    }

    @RequestMapping(value = "pointDetails", method = RequestMethod.POST)
    public @ResponseBody
    Map<String, Object> pointDetails(Long id) {

        Subject subject = SecurityUtils.getSubject();

        Map<String, Object> map = new HashMap<String, Object>();

        if (subject.isPermitted("zhuanxian")) {

            List<OrderLocation> orderLocations = new ArrayList<OrderLocation>();
            List<OrderLocationMany> orderLocationManys = orderLocationManyService.selectByOrderTypeAndOrderId(OrderLocation.OrderType.zhuanxian, id);
            if (!CollectionUtils.isEmpty(orderLocationManys)) {
                OrderLocationMany orderLocationMany = orderLocationManys.get(0);
                Gson gson = new Gson();
                List<OrderLocationGroup> locs = gson.fromJson(orderLocationMany.getJsonLocs(), new TypeToken<List<OrderLocationGroup>>() {
                }.getType());

                if (!CollectionUtils.isEmpty(locs)) {
                    for (OrderLocationGroup og : locs) {
                        OrderLocation orderLocation = new OrderLocation();
                        orderLocation.setSortId(og.getId());
                        orderLocation.setLatitude(og.getLatitude());
                        orderLocation.setLongitude(og.getLongitude());
                        orderLocation.setRadius(og.getRadius());
                        orderLocation.setDirection(og.getDirection());
                        orderLocation.setLocType(og.getLocType());
                        orderLocation.setLocDate(new Date(og.getLocDate()));
                        orderLocation.setRun(og.getRun());
                        orderLocations.add(orderLocation);
                    }
                }
            }
            // List<OrderLocation> orderLocations =
            // orderLocationService.selectByOrderTypeAndOrderId(OrderLocation.OrderType.zhuanxian,id);

            if (CollectionUtils.isEmpty(orderLocations)) {
                List<OrderLngLat> maplist = new ArrayList<OrderLngLat>();
                OrderOrbit orderOrbit = zhuanxianService.findOrbitByOrderId(id);
                if (null != orderOrbit) {
                    maplist = orderOrbit.getLngAndLat();
                }
                if (!CollectionUtils.isEmpty(maplist)) {
                    for (OrderLngLat orderLngLat : maplist) {
                        OrderLocation orderLocation = new OrderLocation();
                        orderLocation.setLatitude(orderLngLat.getLat());
                        orderLocation.setLongitude(orderLngLat.getLng());
                        orderLocations.add(orderLocation);
                    }
                }
            }

            double runDistance = 0;
            double waitDistance = 0;
            if (!CollectionUtils.isEmpty(orderLocations)) {
                Double lastLng = null;
                Double lastLat = null;
                Integer lastRun = null;

                Double firstLng = null;
                Double firstLat = null;

                for (OrderLocation orderLocation : orderLocations) {

                    Double thisLng = null;
                    Double thisLat = null;
                    Integer thisRun = null;

                    thisLng = orderLocation.getLongitude();
                    thisLat = orderLocation.getLatitude();
                    thisRun = orderLocation.getRun();

                    if (null == firstLng && null == firstLat) {
                        firstLng = thisLng;
                        firstLat = thisLat;
                    }

                    if (null != lastLng && null != lastLat && null != thisLng && null != thisLat) {
                        if (null != lastRun && null != thisRun) {
                            if ((lastRun == 1 && thisRun == 1) || (lastRun == 0 && thisRun == 1)) {
                                runDistance += Distance.doubleVal(lastLat, lastLng, thisLat, thisLng);
                            } else {
                                waitDistance += Distance.doubleVal(lastLat, lastLng, thisLat, thisLng);
                            }
                        }

                    }

                    lastLng = thisLng;
                    lastLat = thisLat;
                    lastRun = thisRun;

                }
                map.put("orderLocations", orderLocations);
                map.put("firstLng", firstLng);
                map.put("firstLat", firstLat);
            }

            map.put("runDistance", new BigDecimal(runDistance).setScale(1, BigDecimal.ROUND_HALF_UP));
            map.put("waitDistance", new BigDecimal(waitDistance).setScale(1, BigDecimal.ROUND_HALF_UP));
            map.put("success", true);
            return map;
        } else {
            map.put("success", false);
            map.put("message", "您没有该权限");
        }

        return map;

    }

    /**
     * 查询催单记录
     */
    @RequestMapping(value = "getCuidanOrders", method = RequestMethod.GET)
    public @ResponseBody
    List<Order> getCuidanOrders() {
        Subject subject = SecurityUtils.getSubject();
        List<Order> cuidanOrders = new ArrayList<Order>();
        ServiceSetting serviceSetting = ServiceUtil.checkOpen();
        if (serviceSetting.isZhuanxian() && subject.isPermitted("zhuanxian")) {
            cuidanOrders = zhuanxianService.selectCuidan();
        }

        return cuidanOrders;
    }

    /**
     * 关闭催单提示框
     */
    @RequestMapping(value = "closeCuidan", method = RequestMethod.POST)
    public @ResponseBody
    void closeCuidan(Long orderId) {
        Subject subject = SecurityUtils.getSubject();
        if (subject.isPermitted("zhuanxian")) {
            zhuanxianService.closeCuidan(orderId);
        }
    }

    /***
     * 2019-07-25 16:28:17 no
     * @param id
     * @param couponMoney
     * @param cashMoney
     * @param signMoney
     * @param balanceMoney
     * @param alipayMoney
     * @param weixinMoney
     * @param content
     * @param driverMoney
     * @param driverPlusMinus
     * @param memberMoney
     * @param memberPlusMinus
     * @param wxMoney
     * @param wxPlusMinus
     * @return
     */
    @RequestMapping(value = "updateRealMoney", method = RequestMethod.POST)
    public synchronized @ResponseBody
    Result<Order> updateRealMoney(Long id, BigDecimal couponMoney, BigDecimal cashMoney,
        BigDecimal signMoney,
        BigDecimal balanceMoney, BigDecimal alipayMoney, BigDecimal weixinMoney, String content,
        BigDecimal driverMoney, Integer driverPlusMinus,
        BigDecimal memberMoney, Integer memberPlusMinus,
        @RequestParam(required = false, value = "wxMoney") BigDecimal wxMoney,
        @RequestParam(required = false, value = "wxPlusMinus") Integer wxPlusMinus) {
        Result<Order> vo = new Result<Order>();

        Subject subject = SecurityUtils.getSubject();
        Principal principal = (Principal) subject.getPrincipal();

        if (subject.isPermitted("modifycash")) {

            if (null == driverMoney || null == memberMoney) {
                vo.setSuccess(false);
                vo.setMessage("无效的服务人员或客户金额");
                return vo;
            }
            if (null == driverPlusMinus || null == memberPlusMinus) {
                vo.setSuccess(false);
                vo.setMessage("未知金额标识");
                return vo;
            }
            Pattern pattern2 = Pattern.compile("^\\+?[0-9][0-9]*(\\.\\d{1,2})?$");
            Matcher match2 = pattern2.matcher(driverMoney.toString());
            Matcher match3 = pattern2.matcher(memberMoney.toString());
            if (match2.matches() == false || match3.matches() == false) {
                vo.setSuccess(false);
                vo.setMessage("无效的服务人员或客户金额，金额最多保留2位小数");
                return vo;
            }

            if (null != wxMoney) {
                Matcher match4 = pattern2.matcher(wxMoney.toString());
                if (match4.matches() == false) {
                    vo.setSuccess(false);
                    vo.setMessage("无效的微信金额，金额最多保留2位小数");
                    return vo;
                }
            }

            if (org.apache.commons.lang3.StringUtils.isBlank(content)) {
                vo.setSuccess(false);
                vo.setMessage("请填写修改原因");
                return vo;
            }

            if (driverPlusMinus != 0) {
                driverMoney = driverMoney.multiply(new BigDecimal(-1));
            }
            if (memberPlusMinus != 0) {
                memberMoney = memberMoney.multiply(new BigDecimal(-1));
            }
            if (null != wxPlusMinus) {
                if (wxPlusMinus != 0) {
                    wxMoney = wxMoney.multiply(new BigDecimal(-1));
                }
            }

            Order order = zhuanxianService.findOne(id);

            String detail = "【%s】修改订单【" + order.getOrderNo() + "】金额，原金额：" + order.getRealPay();

            if (null != couponMoney) {
                detail += "，修改后优惠券金额：" + couponMoney;
            }
            if (null != cashMoney) {
                detail += "，修改后代付金额：" + cashMoney;
            }
            if (null != signMoney) {
                detail += "，修改后签单金额：" + signMoney;
            }
            if (null != balanceMoney) {
                detail += "，修改后余额金额：" + balanceMoney;
            }
            if (null != alipayMoney) {
                detail += "，修改后支付宝金额：" + alipayMoney;
            }
            if (null != weixinMoney) {
                detail += "，修改后微信金额：" + weixinMoney;
            }

            detail += "，备注：" + content + "";

            vo = zhuanxianService.updateRealMoney(order, couponMoney, cashMoney, signMoney, balanceMoney, alipayMoney, weixinMoney, driverMoney,
                    memberMoney, wxMoney, content);

            OperationLogEvent operationLogEvent = new OperationLogEvent(principal, detail);
            applicationEventMulticaster.multicastEvent(operationLogEvent);

        } else {
            vo.setSuccess(false);
            vo.setMessage("您没有该权限");
        }

        return vo;
    }

    @RequestMapping(value = "getHistoryInputedPlace", method = RequestMethod.GET)
    public @ResponseBody
    List<PlaceInputHistory> getHistoryInputedPlace(String city, String keyword) {

        // List<PlaceInputHistory> list =
        // placeInputHistoryService.findByKeywords(keyword);
        List<PlaceInputHistory> list = new ArrayList<PlaceInputHistory>();
        try {
            if (CollectionUtils.isEmpty(list)) {
                Subject currentUser = SecurityUtils.getSubject();
                Principal principal = (Principal) currentUser.getPrincipal();

                if (StringUtils.isBlank(city)) {
                    Company company = companyService.findOne(principal.getCompanyId());
                    city = company.getCityName();
                }

                JSONArray placesArray = HttpClientUtil.getPlacesByCityName(keyword, city);
                if (null != placesArray && placesArray.length() > 0) {
                    for (int i = 0; i < placesArray.length(); i++) {
                        PlaceInputHistory ph = new PlaceInputHistory();
                        JSONObject jobj = (JSONObject) placesArray.get(i);
                        LoggerFactory.getLogger(ZhuanxianController.class).info(jobj.toString());
                        if (null != jobj.get("location")) {
                            // ph.setAddress(jobj.optString("name"));
                            double lng = jobj.getJSONObject("location").optDouble("lng");
                            ph.setLongitude(lng);
                            double lat = jobj.getJSONObject("location").optDouble("lat");
                            ph.setLatitude(lat);
                            String placeByLngAndLat = HttpClientUtil.getPlaceByLngAndLat(lng, lat);
                            ph.setAddress(placeByLngAndLat);
                            list.add(ph);
                        }
                    }
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return list;

    }




    private boolean isAreaIdExist(List<Area> areaList, long id, boolean flag) {
        for (Area area : areaList) {
            // 如果遍历到立即tangzu收费标准还存在收费标准列表，终止循环,不改变值(flag=true)
            if (id == area.getId()) {
                flag = true;
                break;
            }
        }
        return flag;
    }

}

class DriverSortGrade implements Comparator<Map<String, Object>> {

    @Override
    public int compare(Map<String, Object> o1, Map<String, Object> o2) {

        return ((Integer) o1.get("grade")).compareTo((Integer) o2.get("grade"));
    }

}
